package com.wechat.utils;

import com.google.gson.Gson;
import com.wechat.constants.WechatConstants;
import com.wechat.constants.WechatResponseConstants;
import com.wechat.pojo.*;
import com.wechat.vo.WechatMenuVo;
import lombok.NonNull;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * @author why
 * @date 2017/12/26 0026
 */
public class WechatUtils {
    public static final Gson gson = new Gson();
    private static final Logger LOGGER = LoggerFactory.getLogger(WechatUtils.class);
    /**
     * 微信公众号id
     */
    private static String wxAppId;
    /**
     * 微信公众号秘钥
     */
    private static String wxAppSecret;

    static {
        wxAppId = PropertiesSingleton.newInstance().getProperties().getProperty("wxAppId");
        wxAppSecret = PropertiesSingleton.newInstance().getProperties().getProperty("wxAppSecret");
    }



    /**
     * 获取微信AccessToken
     * 当微信返回服务器错误时，  WechatAuthorization可能为空
     *
     * @return WechatAuthorization
     */
    public static String getWechatAccessToken() {
        String url = WechatConstants.WECHAT_ACCESS_TOKEN_URL + "&appid=" + wxAppId + "&secret=" + wxAppSecret;
        String responseStr = HttpClientUtils.doGet(url);
        WechatAuthorization wechatAuthorization = null;
        if (!StringUtils.isNoneBlank(responseStr)) {
            wechatAuthorization = gson.fromJson(responseStr, WechatAuthorization.class);
            if(StringUtils.isNoneBlank(wechatAuthorization.getErrcode())){
                if(WechatResponseConstants.INVALID_APPID.equals(wechatAuthorization.getErrcode())){
                    LOGGER.error("微信公众号Appid错误，请检查");
                }else if(WechatResponseConstants.NOTINWHITELIST.equals(wechatAuthorization.getErrcode())){
                    LOGGER.error("程序运行的机器ip不在微信公众号白名单中，请检查");
                }else if(WechatResponseConstants.APPSECRETNOTRIGHT.equals(wechatAuthorization.getErrcode())){
                    LOGGER.error("AppSecret错误或者AppSecret不属于这个公众号，请开发者确认AppSecret的正确性");
                }
            }else{
                return wechatAuthorization.getAccess_token();
            }
        }
        return null;
    }


    /**
     * 微信公众号使用静默方法获取微信用户信息授权字段
     * 当微信返回服务器错误时，WechatAuthorization 可能为空
     *
     * @param code
     * @return
     */
    public static WechatAuthorization getWechatAuthorization(@NonNull String code) {
        Map<String, String> parameterMap = new HashMap<String, String>(6);
        parameterMap.put("appid", wxAppId);
        parameterMap.put("secret", wxAppSecret);
        parameterMap.put("code", code);
        parameterMap.put("grant_type", "authorization_code");
        String responseStr = "";
        try {
            responseStr = HttpClientUtils.doPost(WechatConstants.WECHAT_AUTHORIZATION_URL, parameterMap);
        } catch (IOException e) {
            e.printStackTrace();
        }

        WechatAuthorization wechatAuthorization = null;
        if (StringUtils.isNoneBlank(responseStr)) {
            wechatAuthorization = gson.fromJson(responseStr, WechatAuthorization.class);
        }
        return wechatAuthorization;
    }

    /**
     * 微信公众号获取微信用户基本信息
     *
     * @param accessToken
     * @param openId
     * @param lang        zh_CN中文或者null
     * @return
     */
    public static WechatUserInfo getWechatUserInfo(@NonNull String accessToken, @NonNull String openId, String lang) {
        WechatUserInfo wechatUserInfo = null;
        if (StringUtils.isNoneBlank(lang)) {
        } else {
            lang = WechatConstants.WechatFont.ZH_CN;
        }
        try {
            String url = WechatConstants.WECHAT_USER_INFO_URL + "access_token=" + accessToken + "&openid=" + openId + "&lang=" + lang;
            String responseStr = HttpClientUtils.doGet(url);

            if (StringUtils.isNoneBlank(responseStr)) {
                wechatUserInfo = gson.fromJson(responseStr, WechatUserInfo.class);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return wechatUserInfo;
    }


    /**
     * 微信公众号获取用户信息,通过code
     *
     * @param code
     * @return
     */
    public static synchronized WechatUserInfo getWxUserInfoByCode(@NonNull String code) {
        WechatAuthorization wechatAuthorization = getWechatAuthorization(code);
        WechatUserInfo wechatUserInfo = getWechatUserInfo(wechatAuthorization.getAccess_token(), wechatAuthorization.getOpenid(), "zh_CN");
        return wechatUserInfo;
    }


    /**
     * 获取第三方登陆授权的AccessToken
     *
     * @param appId
     * @param secret
     * @param code
     * @return
     */
    public static WechatAuthorization getThirdAppAccessToken(@NonNull String appId, @NonNull String secret, @NonNull String code) {
        String url = WechatConstants.THIRD_PARTY_WECHAT_AUTHORIZATION_URL + "appid=" + appId + "&secret=" + secret + "&code=" + code + "&grant_type=authorization_code";
        String responseStr = HttpClientUtils.doGet(url);
        System.out.println(responseStr);

        WechatAuthorization wechatAuthorization = gson.fromJson(responseStr, WechatAuthorization.class);
        return wechatAuthorization;
    }

    /**
     * 获取第三方登陆授权的用户基本信息
     *
     * @param accessToken
     * @param openId
     * @return
     */
    public static WechatUserInfo getThirdAppWechatUserInfo(@NonNull String accessToken, @NonNull String openId, String lang) {
        String url = WechatConstants.THIRD_PARTY_WECHAT_USER_INFO_URL + "access_token=" + accessToken + "&openid=" + openId;
        String responseStr = HttpClientUtils.doGet(url);
        WechatUserInfo wechatUserInfo = null;

        if (StringUtils.isNoneBlank(responseStr)) {
            wechatUserInfo = gson.fromJson(responseStr, WechatUserInfo.class);
        }
        return wechatUserInfo;
    }


    /**
     * 第三方登陆获取用户信息,通过code
     *
     * @param code
     * @param appId
     * @param secret
     * @return
     */
    public static WechatUserInfo getThirdAppUserInfoByCode(@NonNull String code, @NonNull String appId, @NonNull String secret) {
        WechatAuthorization wechatAuthorization = getThirdAppAccessToken(appId, secret, code);
        WechatUserInfo wechatUserInfo = getThirdAppWechatUserInfo(wechatAuthorization.getAccess_token(), appId, secret);
        return wechatUserInfo;
    }

    /**
     * 创建微信底部菜单
     *
     * @param accessToken
     * @param wechatMenuVos
     */
    public static void createWechatMenu(@NonNull String accessToken, List<WechatMenuVo> wechatMenuVos) {

        WechatMenu wechatMenu = new WechatMenu();
        List<WechatMenu.ButtonEntity> listButtonEntity = new ArrayList<WechatMenu.ButtonEntity>();
        for (WechatMenuVo vo : wechatMenuVos) {
            WechatMenu.ButtonEntity buttonEntity = new WechatMenu.ButtonEntity();
            buttonEntity.setName(vo.getFatherButtonName());
            List<WechatMenu.ButtonEntity.SubButtonEntity> listSubButton = new ArrayList<WechatMenu.ButtonEntity.SubButtonEntity>();
            for (WechatMenuVo.SubButtonEntity subButtonVo : vo.getSubButtonEntityList()) {
                WechatMenu.ButtonEntity.SubButtonEntity subButton = new WechatMenu.ButtonEntity.SubButtonEntity();
                subButton.setName(subButtonVo.getSubButtonName());
                subButton.setType(subButtonVo.getSubButtonType());
                subButton.setKey(subButtonVo.getSubButtonKey());
                subButton.setUrl(subButtonVo.getSubButtonUrl());
                listSubButton.add(subButton);
            }
            buttonEntity.setSubButton(listSubButton);
            listButtonEntity.add(buttonEntity);
        }
        wechatMenu.setButton(listButtonEntity);
        HttpClientUtils.postJson(WechatConstants.WECHAT_CREATE_MENU_URL + accessToken, gson.toJson(wechatMenu));
    }

    /**
     * 获取js接口访问的ticket凭据
     *
     * @return
     */
    public static String getJsApiTicket(@NonNull String accessToken) {
        StringBuffer buffer = new StringBuffer(WechatConstants.WECHAT_JS_API_URL);
        buffer.append("access_token=");
        if (StringUtils.isNoneBlank(accessToken)) {
            buffer.append(accessToken);
        } else {
            buffer.append(getWechatAccessToken());
        }
        buffer.append("&type=jsapi");
        String jsApiTicket = HttpClientUtils.doGet(buffer.toString());
        WechatJsAuthorization wechatJsAuthorization = gson.fromJson(jsApiTicket, WechatJsAuthorization.class);
        return wechatJsAuthorization.getTicket();
    }

    /**
     * 获取jsapi相关参数map
     *
     * @param jsApiTicket 获取到的js访问凭据
     * @param url
     * @return
     */
    public static Map<String, String> getJsSignMap(@NonNull String jsApiTicket, String url) {
        Map<String, String> map = new HashMap<String, String>(10);
        String nonceStr = SignUtils.getNonceStr();
        String timeStamp = SignUtils.getTimeStamp();
        String s = "jsapi_ticket=" + jsApiTicket + "&noncestr=" + nonceStr + "&timestamp=" + timeStamp + "&url=" + url;
        String signature = SignUtils.signature(s);
        map.put("appId", wxAppId);
        map.put("url", url);
        map.put("jsapi_ticket", jsApiTicket);
        map.put("nonceStr", nonceStr);
        map.put("timestamp", timeStamp);
        map.put("signature", signature);
        return map;
    }
}